package org.nativejpa.query;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;

/**
 * interface for get Object from ResultSet and set Object to PreparedStatement
 *
 * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
 * @create 2009-3-18 15:49:28
 */
public abstract class JDBCMapper {

    public static enum DbType {
        MYSQL("MySQL"), DB2("DB2"),
        ORACLE("Oracle"), HSQL("HSQL"),
        SQLSERVER("SQLServer"), POSTGRESQL("PostgreSQL"),
        INFORMIX("Informix"), SYBASE("Sybase"),
        DERBY("Derby"), UNKNOWN("Unknown");

        private String type;

        DbType(String type) {
            this.type = type;
        }

        @Override
        public String toString() {
            return type;
        }
    }

    public static JDBCMapper getJDBCMapper(String dbProductName) {
        //TODO: implement other JDBCMapper
        if (dbProductName == null || dbProductName.trim().equals("") || dbProductName.trim().equalsIgnoreCase("Unknown")) {
            return new DefaultJDBCMapper();
        }
        DbType dbType = detectDatabaseType(dbProductName);
        if (dbType.equals(DbType.MYSQL)) {
            return new DefaultJDBCMapper();
        }
        else if (dbType.equals(DbType.ORACLE)) {
            return new OracleJDBCMapper();
        }
        else {
            return new DefaultJDBCMapper();
        }
    }

    public static DbType detectDatabaseType(String dbProductName) {
        DbType databaseType;
        dbProductName = dbProductName.toUpperCase();
        if (dbProductName.indexOf("ORACLE") >= 0) {
            databaseType = DbType.ORACLE;
        }
        else if (dbProductName.indexOf("MYSQL") >= 0) {
            databaseType = DbType.MYSQL;
        }
        else if (dbProductName.indexOf("DB2") >= 0) {
            databaseType = DbType.DB2;
        }
        else if (dbProductName.indexOf("MICROSOFT SQL SERVER") >= 0) {
            databaseType = DbType.SQLSERVER;
        }
        else if (dbProductName.indexOf("POSTGRESQL") >= 0) {
            databaseType = DbType.POSTGRESQL;
        }
        else if (dbProductName.indexOf("SYBASE") >= 0) {
            databaseType = DbType.SYBASE;
        }
        else if (dbProductName.indexOf("INFORMIX") >= 0) {
            databaseType = DbType.INFORMIX;
        }
        else if (dbProductName.indexOf("DERBY") >= 0) {
            databaseType = DbType.DERBY;
        }
        else if (dbProductName.indexOf("HSQL") >= 0) {
            databaseType = DbType.HSQL;
        }
        else {
            databaseType = DbType.UNKNOWN;
        }
        return databaseType;
    }

    /**
     * convert row to Entity Object
     */
    protected abstract Object getResultSetObject(final ResultSet rset, Class columnClass, int columnIndex) throws SQLException;

    /**
     * set Object to PreparedStatement correctly
     */
    protected abstract void setPreparedStatementObject(final PreparedStatement pst, int index, Object value) throws SQLException;

}
